/*******************************************************************************
 * Copyleft (c) 2021 Kcode
 *
 * @file    rgb2rgb.c
 * @brief   转换视频数据格式，把摄像头原始的rgb565格式转换成rgb565或32格式
 * @author  K
 * @version 0.0.1
 * @date    2021-07-26
 * @license MulanPSL-1.0
 *
 * 文件修改历史：
 * <时间>       | <版本>    | <作者>  | <描述>
 * 2021-07-27   | v0.0.1    | Kcode   | 转换视频数据格式
 * -----------------------------------------------------------------------------
 ******************************************************************************/

#include <linux/videodev2.h>
#include <stdlib.h>
#include <string.h>

#include "convert_manager.h"

/*!
 * @brief  判断输入输出格式是否为rgb和rgb
 * @return  0：不支持 1：支持
 */
static int isSupportRgb2Rgb(int pixel_format_in, int pixel_format_out)
{
    if (pixel_format_in != V4L2_PIX_FMT_RGB565)
        return 0;
    
    if ((pixel_format_out != V4L2_PIX_FMT_RGB565) && \
        (pixel_format_out != V4L2_PIX_FMT_RGB32))
        return 0;

    return 1;
}
 
/*!
 * @brief  支持的格式转换rgb为输出格式rgb565
 *         参考luvcview
 * @return  0：成功 -1：失败
 */
static int Rgb2RgbConvert(PT_VIDEOBUF videobuf_in, PT_VIDEOBUF videobuf_out)
{
    PT_PIXELDATAS pixeldatas_in   = &videobuf_in->pixel_data;
    PT_PIXELDATAS pixeldatas_out = &videobuf_out->pixel_data;

    int x, y;
    int r, g, b;
    int color;
    unsigned short *pSrc = (unsigned short *)pixeldatas_in->PixelDatas;
    unsigned int *pDest  = (unsigned int *)pixeldatas_in->PixelDatas;

    if (videobuf_in->pixel_format != V4L2_PIX_FMT_RGB565)
    {
        return -1;
    }
    
    /*!
     * 根据输入格式，调用不同的转换
     */
    if (videobuf_in->pixel_format == V4L2_PIX_FMT_RGB565)
    {
        /*!
         * 设置
         */
        pixeldatas_out->width      = pixeldatas_in->width;
        pixeldatas_out->height     = pixeldatas_in->height;
        pixeldatas_out->bpp        = pixeldatas_in->bpp;
        pixeldatas_out->linebytes  = pixeldatas_out->width * pixeldatas_out->bpp / 8;
        pixeldatas_out->TotalBytes = pixeldatas_out->linebytes * pixeldatas_out->height;

        if (NULL == pixeldatas_out->PixelDatas)
        {
            pixeldatas_out->PixelDatas = (unsigned char *)malloc(pixeldatas_out->TotalBytes);
            if (pixeldatas_out->PixelDatas == NULL)
                return -1;
        }

        /*!
         * 处理数据
         */
        memcpy(pixeldatas_out->PixelDatas, pixeldatas_in->PixelDatas,
                                            pixeldatas_out->TotalBytes);
    }
    else if (videobuf_in->pixel_format == V4L2_PIX_FMT_RGB32)
    {
        /*!
         * 设置
         */
        pixeldatas_out->width      = pixeldatas_in->width;
        pixeldatas_out->height     = pixeldatas_in->height;
        pixeldatas_out->bpp        = 16;
        pixeldatas_out->linebytes  = pixeldatas_out->width * pixeldatas_out->bpp / 8;
        pixeldatas_out->TotalBytes = pixeldatas_out->linebytes * pixeldatas_out->height;

        if (NULL == pixeldatas_out->PixelDatas)
        {
            pixeldatas_out->PixelDatas = (unsigned char *)malloc(pixeldatas_out->TotalBytes);
            if (pixeldatas_out->PixelDatas == NULL)
                return -1;
        }

        /*!
         * 逐行处理数据
         */
        pDest = (unsigned int *)pixeldatas_out->PixelDatas;
        for (y = 0; y < pixeldatas_out->height; y++)
        {
            for (x = 0; y < pixeldatas_out->width; x++)
            {
                color = *pSrc++;

                /* 从RGB565格式的数据中提取出R,G,B */
                r = color >> 11;
                g = (color >> 5) & 0x3F;
                b = color & 0x1F;

                /* 把提取出的R,G,B转为0x00RRGGBB的32位数据 */
                color = ((r << 3) << 16) | ((g << 2) << 8) | (b << 3);

                /* 存入目的地址 */
                *pDest = color;
                pDest++;
            }
        }
    }
    
    return 0;
}
 
/*!
 * @brief  退出函数，释放内存
 * @return  0
 */
static int Rgb2RgbConvertExit(PT_VIDEOBUF videobuf_out)
{
    if (videobuf_out->pixel_data.PixelDatas == NULL)
    {
        free(videobuf_out->pixel_data.PixelDatas);
        videobuf_out->pixel_data.PixelDatas = NULL;
    }

    return 0;
}

 static T_VIDEOCONVERTOPR s_Rgb2RgbConvert = {
     .name  = "rgb2rgb",
     .isSupport   = isSupportRgb2Rgb,
     .Convert     = Rgb2RgbConvert,
     .ConvertExit = Rgb2RgbConvertExit,
 };
 
/*!
 * @brief  初始化函数，把对支持的各个转换格式进行初始化工作
 *         对应的结构体放入链表统一管理
 * @return  0：初始化成功 1：失败
 */
 int Rgb2RgbInit(void)
 {
     return RegisterVideoConvertOpr(&s_Rgb2RgbConvert);
 }


